package com.timguan.render.service.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.timguan.common.cache.service.ConcurrentCacheHelper;
import com.timguan.render.api.api.backend.CMSPageService;
import com.timguan.render.api.api.backend.CMSRouteService;
import com.timguan.render.api.api.http.CMSNativeDataService;
import com.timguan.render.api.constants.ResourceConstants;
import com.timguan.render.api.entity.cms.*;
import com.timguan.render.dao.domain.cms.CmsDataBindingDO;
import com.timguan.render.dao.domain.cms.CmsPageDO;
import com.timguan.render.dao.domain.cms.CmsPageDOWithBLOBs;
import com.timguan.render.dao.domain.cms.CmsResourceConfigDO;
import com.timguan.render.dao.manager.cms.CmsABTestManagerImpl;
import com.timguan.render.dao.manager.cms.CmsDataBindingManagerImpl;
import com.timguan.render.dao.manager.cms.CmsPageManagerImpl;
import com.timguan.render.dao.manager.cms.CmsResourceConfigManagerImpl;
import com.timguan.render.dataprocessor.processor.CommonParametersWrapper;
import com.timguan.render.dataprocessor.processor.DataProcessor;
import com.timguan.render.dataprocessor.processor.PaginationDataListProcessor;
import com.timguan.render.service.common.B2CMallConstants;
import com.timguan.render.service.common.CacheService;
import net.pocrd.entity.ServiceException;
import net.pocrd.entity.ServiceRuntimeException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.*;

/**
 * cms page
 * Created by guankaiqiang on 2015/3/18.
 */
public class CMSPageServiceImpl implements CMSPageService, CMSNativeDataService, ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(CMSPageServiceImpl.class);
    @Autowired
    private CmsDataBindingManagerImpl cmsDataBindingManagerImpl;
    @Autowired
    private CmsPageManagerImpl cmsPageManagerImpl;
    @Autowired
    private CMSRouteServiceImpl cmsTopicServiceImpl;
    @Autowired
    private CmsABTestManagerImpl cmsABTestManagerImpl;
    @Autowired
    private CmsResourceConfigManagerImpl cmsResourceConfigManagerImpl;
    @Autowired
    private CacheService cacheService;
    protected ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Map<String, List<List<Object>>> getDataOfPage(int pageId, int appId) throws ServiceException {
        List<CmsDataBindingDO> cmsDataBindingDOs = cmsDataBindingManagerImpl.getBindingListIdsOfPage(pageId);
        return cmsDataBindingDOs != null ? getDataOfPage(appId, cmsDataBindingDOs) : null;
    }

    @Override
    public List<CMSResourceConfig> getResourceConfigsOfPage(int pageId) throws ServiceException {
        CmsPageDO cmsPageDO = cmsPageManagerImpl.selectByPrimaryKey(pageId);
        String headerName = null, footerName = null, versionName = null;
        if (cmsPageDO != null) {
            footerName = cmsPageDO.getPageType() == B2CMallConstants.PC_PAGE_TYPE ? ResourceConstants.PC_DEFAULT_FOOTER_NAME : ResourceConstants.H5_DEFAULT_FOOTER_NAME;
            headerName = cmsPageDO.getHeaderName();
            versionName = cmsPageDO.getPageType() == B2CMallConstants.PC_PAGE_TYPE ? ResourceConstants.PC_BASE_RESOURCE_VERSION : ResourceConstants.H5_BASE_RESOURCE_VERSION;
        }
        List<CMSResourceConfig> cmsResourceConfigs = null;
        List<CmsResourceConfigDO> cmsResourceConfigDOs = cmsResourceConfigManagerImpl.getCmsResourceConfigDOByNames(headerName, footerName, versionName);
        if (cmsResourceConfigDOs != null && cmsResourceConfigDOs.size() != 0) {
            cmsResourceConfigs = new ArrayList<CMSResourceConfig>(cmsResourceConfigDOs.size());
            for (CmsResourceConfigDO cmsResourceConfigDO : cmsResourceConfigDOs) {
                CMSResourceConfig cmsResourceConfig = new CMSResourceConfig();
                cmsResourceConfig.setResType(cmsResourceConfigDO.getResType());
                cmsResourceConfig.setDesc(cmsResourceConfigDO.getDescription());
                cmsResourceConfig.setName(cmsResourceConfigDO.getName());
                cmsResourceConfig.setValue(cmsResourceConfigDO.getValue());
                cmsResourceConfigs.add(cmsResourceConfig);
            }
        }
        return cmsResourceConfigs;
    }

    /**
     * 子模块数据封装
     */
    private static class SubModuleDataWrapper {
        private int listId;
        private String processor;
        private List<Object> dataList;

        public String getProcessor() {
            return processor;
        }

        public void setProcessor(String processor) {
            this.processor = processor;
        }

        /**
         * 子模块数据封装
         *
         * @param listId
         * @param dataList
         */
        public SubModuleDataWrapper(Integer listId, List<Object> dataList) {
            this.listId = listId != null ? listId : 0;
            this.dataList = dataList;
        }

        /**
         * 子模块数据封装
         *
         * @param listId
         * @param dataList
         * @param processor
         */
        public SubModuleDataWrapper(Integer listId, List<Object> dataList, String processor) {
            this.listId = listId != null ? listId : 0;
            this.dataList = dataList;
            this.processor = processor;
        }

        public int getListId() {
            return listId;
        }

        public void setListId(Integer listId) {
            this.listId = listId != null ? listId : 0;
        }

        public List<Object> getDataList() {
            return dataList;
        }

        public void setDataList(List<Object> dataList) {
            this.dataList = dataList;
        }

    }

    /**
     * 模块级别数据由placeHolder做对应（模块在页面内的唯一ID）,模块内的数据按照subModule在Module种的顺序对应到dataBinding中的顺序
     * List<List<Object>>module中的数据列表，按照submodule的顺序（submoduleId降序）
     * List<Object>submodule的数据列表，内部数据顺序由process保证
     *
     * @param cmsDataBindingDOs
     */
    private Map<String, List<List<Object>>> getDataOfPage(int appid, List<CmsDataBindingDO> cmsDataBindingDOs) {
        Map<String, List<List<Object>>> result = new HashMap<String, List<List<Object>>>();
        for (CmsDataBindingDO cmsDataBindingDO : cmsDataBindingDOs) {
            List<List<Object>> dataOfModule = result.get(cmsDataBindingDO.getPlaceholder());
            if (dataOfModule == null) {
                dataOfModule = new ArrayList<List<Object>>();
            }
            Object bean = applicationContext.getBean(cmsDataBindingDO.getProcessor());
            List<Object> dataOfSubModule = null;
            if (bean != null && bean instanceof DataProcessor) {
                DataProcessor processor = (DataProcessor) bean;
                //spmABC设置
                CommonParametersWrapper commonParametersWrapper = new CommonParametersWrapper(appid, cmsDataBindingDO.getPageId(),
                        cmsDataBindingDO.getId());
                dataOfSubModule = processor.getResult(commonParametersWrapper, cmsDataBindingDO.getProcessorParams());
            } else {
                logger.error("unkown processor,processor:{}", cmsDataBindingDO.getProcessor());
            }
            if (dataOfSubModule == null) {
                dataOfSubModule = new ArrayList<Object>();
            }
            dataOfModule.add(dataOfSubModule);
            result.put(cmsDataBindingDO.getPlaceholder(), dataOfModule);
        }
        return result;
    }

    /**
     * 子楼层顺序
     *
     * @param appid
     * @param cmsDataBindingDOs
     */
    private Map<String, List<SubModuleDataWrapper>> getDataOfPageWithWrapper(int appid, List<CmsDataBindingDO> cmsDataBindingDOs) {
        Map<String, List<SubModuleDataWrapper>> result = new HashMap<String, List<SubModuleDataWrapper>>();
        for (CmsDataBindingDO cmsDataBindingDO : cmsDataBindingDOs) {
            List<SubModuleDataWrapper> dataOfModule = result.get(cmsDataBindingDO.getPlaceholder());
            if (dataOfModule == null) {
                dataOfModule = new ArrayList<SubModuleDataWrapper>();
            }
            Object bean = applicationContext.getBean(cmsDataBindingDO.getProcessor());
            List<Object> dataOfSubModule = null;//子楼层数据
            if (bean != null && bean instanceof DataProcessor) {
                DataProcessor processor = (DataProcessor) bean;
                CommonParametersWrapper commonParametersWrapper = new CommonParametersWrapper(appid, cmsDataBindingDO.getPageId(),
                        cmsDataBindingDO.getId());
                dataOfSubModule = processor.getResult(commonParametersWrapper, cmsDataBindingDO.getProcessorParams());
            } else {
                logger.error("unkown processor,processor:{}", cmsDataBindingDO.getProcessor());
            }
            if (dataOfSubModule == null) {
                dataOfSubModule = new ArrayList<Object>();
            }
            dataOfModule.add(new SubModuleDataWrapper(cmsDataBindingDO.getListId(), dataOfSubModule, cmsDataBindingDO.getProcessor()));
            result.put(cmsDataBindingDO.getPlaceholder(), dataOfModule);
        }
        return result;
    }

    /**
     * 判断模块数据是否为空
     *
     * @param dataOfModule
     */
    private boolean isDataOfModuleEmpty(List<SubModuleDataWrapper> dataOfModule) {
        if (dataOfModule != null) {
            for (SubModuleDataWrapper element : dataOfModule) {
                if (element != null && element.getDataList() != null && element.getDataList().size() != 0) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 静态模块（无数据/客户端调用接口等）
     *
     * @param placeHoder
     * @param cmsDataBindingDOs
     */
    private boolean isStaticModule(String placeHoder, List<CmsDataBindingDO> cmsDataBindingDOs) {
        if (cmsDataBindingDOs != null) {
            for (CmsDataBindingDO cmsDataBindingDO : cmsDataBindingDOs) {
                if (placeHoder.equalsIgnoreCase(cmsDataBindingDO.getPlaceholder())) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 根据页面名称获取数据
     *
     * @param pageId
     */
    private PData getDataByPageId(int appId, int pageId) {
        CmsPageDOWithBLOBs cmsPageDO = cmsPageManagerImpl.selectByPrimaryKey(pageId);
        //页面布局
        if (cmsPageDO == null || StringUtils.isBlank(cmsPageDO.getPageConfig())) {
            return null;
        }
        CMSPageConfig cmsPageConfig = JSON.parseObject(cmsPageDO.getPageConfig(), CMSPageConfig.class);
        if (cmsPageConfig == null || cmsPageConfig.getPageLayoutConfigs() == null || cmsPageConfig.getPageLayoutConfigs().size() == 0) {
            return null;
        }
        CMSPageConfig.PageLayoutConfig pageLayoutConfig = cmsPageConfig.getPageLayoutConfigs().get(0);
        if (pageLayoutConfig.getLayoutModuleConfigs() == null || pageLayoutConfig.getLayoutModuleConfigs().size() == 0) {
            return null;
        }
        //获取楼层数据绑定记录
        List<CmsDataBindingDO> cmsDataBindingDOs = cmsDataBindingManagerImpl.getBindingListIdsOfPage(pageId);
        if (cmsDataBindingDOs == null || cmsDataBindingDOs.size() == 0) {
            return null;
        }
        //获取楼层数据
        Map<String, List<SubModuleDataWrapper>> dataOfPage = getDataOfPageWithWrapper(appId, cmsDataBindingDOs);
        if (dataOfPage == null || dataOfPage.size() == 0) {
            return null;
        }
        PData pData = new PData();
        pData.pageId = cmsPageDO.getId();
        pData.backgroundColor = cmsPageConfig.getBackgroundColor();
        pData.backgroundUrl = cmsPageConfig.getBackgroundUrl();
        pData.shareIcon = cmsPageConfig.getShareIcon();
        pData.title = cmsPageDO.getTitle();
        pData.description = cmsPageDO.getDescription();
        pData.mDatas = new ArrayList<MData>();

        List<CMSPageConfig.LayoutModuleConfig> layoutModuleConfigs = pageLayoutConfig.getLayoutModuleConfigs();
        Map<String, Long> timeMap = new HashMap<String, Long>();
        //把相同类型的分组
        Map<String, List<CMSPageConfig.LayoutModuleConfig>> bocketList = getModuleTypeGroup(layoutModuleConfigs, timeMap);
        //分组按照每小时进行一次轮播
        sortedGroup(bocketList, timeMap);

        for (int i = 0, len = layoutModuleConfigs.size(); i < len; i++) {
            //获取匹配的数据
            CMSPageConfig.LayoutModuleConfig layoutModuleConfig = getRightData(bocketList, layoutModuleConfigs.get(i));
            List<SubModuleDataWrapper> dataOfModule = dataOfPage.get(layoutModuleConfig.getPlaceHolder());
            //静态模块/模块存在数据，添加数据节点
            if (isStaticModule(layoutModuleConfig.getPlaceHolder(), cmsDataBindingDOs) || !isDataOfModuleEmpty(dataOfModule)) {
                MData mData = new MData();
                mData.mId = layoutModuleConfig.getPlaceHolder();
                mData.mType = layoutModuleConfig.getModuleName();
                mData.title = layoutModuleConfig.getModuleTitle();
                mData.mDescription = layoutModuleConfig.getModuleSubTitle();
                mData.mSDescription = layoutModuleConfig.getShortDescription();
                mData.specialContent = layoutModuleConfig.getSpecialContent();
                mData.mLogo = layoutModuleConfig.getModuleLogo();
                mData.headType = layoutModuleConfig.getHeadType();
                mData.rightLink = layoutModuleConfig.getRightLink();
                mData.style = layoutModuleConfig.getStyle();
                if (dataOfModule != null) {
                    mData.subMDatas = new ArrayList<SubMData>();
                    for (SubModuleDataWrapper dataOfSubModule : dataOfModule) {
                        SubMData subMData = new SubMData();
                        subMData.datas = new ArrayList<String>();
                        //设置模块是否分页属性
                        String processor = dataOfSubModule.getProcessor();
                        if (dataOfSubModule.getDataList() != null) {
                            for (Object element : dataOfSubModule.getDataList()) {
                                subMData.datas.add(JSON.toJSONString(element));
                            }
                        }
                        //分页处理器
                        if (DataProcessor.PAGINATION_PROCESSOR.equals(processor) && subMData.datas.size() == PaginationDataListProcessor.PAGE_SIZE) {
                            subMData.hasMore = true;
                        }
                        subMData.listId = dataOfSubModule.getListId();
                        mData.subMDatas.add(subMData);
                    }
                }
                pData.mDatas.add(mData);
            }
        }
        return pData;
    }

    /**
     * 根据moduleType进行分组
     *
     * @param layoutModuleConfigs
     */
    private Map<String, List<CMSPageConfig.LayoutModuleConfig>> getModuleTypeGroup(List<CMSPageConfig.LayoutModuleConfig> layoutModuleConfigs,
                                                                                   Map<String, Long> timeMap) {
        //把相同类型的分组
        Map<String, List<CMSPageConfig.LayoutModuleConfig>> bucketList = null;
        if (layoutModuleConfigs != null && layoutModuleConfigs.size() > 0) {
            int len = layoutModuleConfigs.size();
            bucketList = new HashMap<String, List<CMSPageConfig.LayoutModuleConfig>>();
            CMSPageConfig.LayoutModuleConfig moduleConfig = null;
            String moduleType = null;
            Boolean isSlide = null;
            List<CMSPageConfig.LayoutModuleConfig> tempList = null;
            for (int i = 0; i < len; i++) {
                moduleConfig = layoutModuleConfigs.get(i);
                moduleType = moduleConfig.getBucket();
                isSlide = moduleConfig.isCanSlide();
                if ((isSlide != null && isSlide) && StringUtils.isNotBlank(moduleType)) {
                    if (timeMap.get(moduleType) == null) {
                        timeMap.put(moduleType, moduleConfig.getSlideTime());
                    }
                    tempList = bucketList.get(moduleType);
                    if (tempList == null) {
                        tempList = new LinkedList<CMSPageConfig.LayoutModuleConfig>();
                        tempList.add(moduleConfig);
                        bucketList.put(moduleType, tempList);
                    } else {
                        tempList.add(moduleConfig);
                    }
                }
            }
        }

        return bucketList;
    }

    /**
     * 对分组列表进行排序
     *
     * @param bocketList
     */
    private void sortedGroup(Map<String, List<CMSPageConfig.LayoutModuleConfig>> bocketList, Map<String, Long> timeMap) {
        if (bocketList == null || bocketList.size() < 1) {
            return;
        }
        Map.Entry<String, Long> temp = null;
        Calendar c = Calendar.getInstance();
        long current = c.getTimeInMillis();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        long today = current - c.getTimeInMillis();
        if (timeMap != null && timeMap.size() > 0) {
            Iterator<Map.Entry<String, Long>> iterator = timeMap.entrySet().iterator();
            while (iterator.hasNext()) {
                temp = iterator.next();
                temp.setValue(today / temp.getValue());
            }
        }
        List<CMSPageConfig.LayoutModuleConfig> items = null;
        int index = 0;
        Long timeGroup = 3600l; //一小时的毫秒数
        for (Map.Entry<String, List<CMSPageConfig.LayoutModuleConfig>> entry : bocketList.entrySet()) {
            items = entry.getValue();
            if (timeMap != null && timeMap.get(entry.getKey()) > 0) {
                timeGroup = timeMap.get(entry.getKey()) / 1000;
            }
            index = (int) (timeGroup % items.size());
            if (index != 0) {
                items = items.subList(0, index);
                entry.getValue().addAll(items);
                //                    items = entry.getValue().subList(0, index);
                //                    entry.getValue().removeAll(items);
                items = entry.getValue();
                entry.setValue(items.subList(index, items.size()));
            }

        }
    }

    /**
     * 获取匹配的数据
     */
    private CMSPageConfig.LayoutModuleConfig getRightData(Map<String, List<CMSPageConfig.LayoutModuleConfig>> bocketList,
                                                          CMSPageConfig.LayoutModuleConfig layoutModuleConfig) {
        CMSPageConfig.LayoutModuleConfig moduleConfig = layoutModuleConfig;
        Boolean canSlide = layoutModuleConfig.isCanSlide();
        if (canSlide) {
            String bucket = layoutModuleConfig.getBucket();
            List<CMSPageConfig.LayoutModuleConfig> list = bocketList.get(bucket);
            if (list != null && list.size() > 0) {
                moduleConfig = list.get(0);
                list.remove(moduleConfig);
            }
        }
        return moduleConfig;
    }

    /**
     * 获取楼层分页数据
     *
     * @param appId
     * @param pageId
     * @param listId
     * @param pageNumber
     * @param cmsDataBindingDO
     */
    private List<Object> getDataOfPageModule(int appId, int pageId, int listId, int pageNumber, CmsDataBindingDO cmsDataBindingDO) {
        Object bean = applicationContext.getBean(cmsDataBindingDO.getProcessor());
        List<Object> dataOfSubModule = null;//子楼层数据
        if (bean != null && bean instanceof DataProcessor) {
            DataProcessor processor = (DataProcessor) bean;
            CommonParametersWrapper commonParametersWrapper = new CommonParametersWrapper(appId, pageId, listId);
            Map<String, String> paramsMap = JSON.parseObject(cmsDataBindingDO.getProcessorParams(), new TypeReference<Map<String, String>>() {
            });
            if (paramsMap != null) {
                paramsMap.put(DataProcessor.PAGE_NUMBER_PARAM, String.valueOf(pageNumber));
                dataOfSubModule = processor.getResult(commonParametersWrapper, JSON.toJSONString(paramsMap));
            }
        } else {
            logger.error("unkown processor,processor:{}", cmsDataBindingDO.getProcessor());
        }
        if (dataOfSubModule == null) {
            dataOfSubModule = new ArrayList<Object>();
        }
        return dataOfSubModule;
    }

    @Override
    public SubMData getSubMData(int appId, int pageId, int listId, int pageNumber) throws ServiceException {
        if (appId <= 0 || pageId <= 0 || listId <= 0) {
            return null;
        }
        if (pageNumber <= 0) {
            pageNumber = 1;
        }
        return cacheService.getConcurrentCacheHelper().getCachedResult(
                cacheService.getServiceCacheConfig(B2CMallConstants.GET_SUBDATA),
                new ConcurrentCacheHelper.Delegate<SubMData>() {
                    @Override
                    public SubMData execute(Object... params) {
                        Integer appId = (Integer) params[0];
                        Integer pageId = (Integer) params[1];
                        Integer listId = (Integer) params[2];
                        Integer pageNumber = (Integer) params[3];
                        SubMData subMData = new SubMData();
                        CmsDataBindingDO cmsDataBindingDO = cmsDataBindingManagerImpl.getBindingInfoByPageIdAndListId(pageId, listId);
                        if (cmsDataBindingDO != null) {
                            List<Object> subModuleData = getDataOfPageModule(appId, pageId, listId, pageNumber, cmsDataBindingDO);
                            if (subModuleData != null && subModuleData.size() != 0) {
                                List<String> dataString = new ArrayList<String>(subModuleData.size());
                                for (Object element : subModuleData) {
                                    dataString.add(JSON.toJSONString(element));
                                }
                                subMData.setDatas(dataString);
                                subMData.hasMore = dataString.size() == PaginationDataListProcessor.PAGE_SIZE + 1;
                            } else {
                                subMData.hasMore = false;
                            }
                            subMData.listId = listId;
                        } else {
                            subMData.hasMore = false;
                            subMData.listId = listId;
                        }
                        return subMData;
                    }
                }, appId, pageId, listId, pageNumber);
    }

    /**
     * app native页面数据获取
     *
     * @param appId
     * @param identify app版本号
     */
    public PData getNativeData(int appId, String appVersion, String identify, String appDeviceId) throws ServiceException {
        //根据deviceId获取分组
        String groupName = groupByDeviceId(appId, appVersion, identify, appDeviceId);
        PData pData = cacheService.getConcurrentCacheHelper().getCachedResult(
                cacheService.getServiceCacheConfig(B2CMallConstants.GET_NATIVE_DATA),
                new ConcurrentCacheHelper.Delegate<PData>() {
                    @Override
                    public PData execute(Object... params) {
                        CMSPage cmsPage = null;
                        Integer appId = (Integer) params[0];
                        String appVersion = (String) params[1];
                        String identify = (String) params[2];
                        String group = (String) params[3];
                        try {
                            //API访问必须经过路由层
                            if (StringUtils.isNumeric(identify)) {
                                cmsPage = cmsTopicServiceImpl
                                        .getCmsPage(CMSRouteService.AccessPlatform.APP_APIGW, null, Integer.parseInt(identify), appId,
                                                appVersion, group);
                            } else {
                                cmsPage = cmsTopicServiceImpl
                                        .getCmsPage(CMSRouteService.AccessPlatform.APP_APIGW, identify, 0, appId, appVersion, group);
                            }
                        } catch (ServiceException e) {
                            logger.error("getCmsPage failed!", e);
                            throw new ServiceRuntimeException("getCmsPage failed!", e);
                        }
                        if (cmsPage == null) {
                            return null;
                        }
                        PData pData = null;
                        if (cmsPage.isNeedInvokeRedirect()) {
                            pData = new PData();
                            pData.needRedirect = true;
                            pData.redirectUrl = cmsPage.getRedirectUrl();
                        } else {
                            pData = getDataByPageId(appId, cmsPage.getPageId());
                        }
                        return pData;
                    }

                }, appId, appVersion, identify, groupName);
        return pData;
    }

    /**
     * 根据设备id进行分组
     * 根据deviceId进行mod100进行分组
     *
     * @param devicedId
     */
    private String groupByDeviceId(int appId, String appVersion, String identify, String devicedId) {
        if (StringUtils.isNotBlank(devicedId)) {
            if (StringUtils.isNumeric(identify)) {
                return cmsABTestManagerImpl.getGroup(appId, appVersion, Integer.parseInt(identify), null, devicedId);
            } else {
                return cmsABTestManagerImpl.getGroup(appId, appVersion, 0, identify, devicedId);
            }
        }
        return null;
    }

}
